package com.gitee.zeric.codec.service;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gitee.zeric.codec.controller.R;
import com.gitee.zeric.codec.entity.SysCodeRuleGenerate;
import com.gitee.zeric.codec.constans.CodeRuleTypeEnum;
import com.gitee.zeric.codec.exception.BizException;
import com.gitee.zeric.codec.generaters.RuleParam;
import com.gitee.zeric.codec.mapper.SysCodeRuleGenerateMapper;
import com.gitee.zeric.codec.model.RuleModel;
import com.gitee.zeric.codec.parser.DefaultCodeRuleParser;
import com.gitee.zeric.codec.util.OrikaUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

/**
 * 系统编码生成规则模块
 *
 * @author zhangjian
 * @date 2021-12-07 14:44:01
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class SysCodeRuleGenerateServiceImpl extends ServiceImpl<SysCodeRuleGenerateMapper, SysCodeRuleGenerate> implements SysCodeRuleGenerateService, InitializingBean {

    private final DefaultCodeRuleParser codeRuleParser;


    @Override
    public List<String> batchGet(String ruleCode, int size) {
        return codeRuleParser.batchUniqParse(ruleCode,size,100);
    }

    @Override
    public List<String> functionTestBatch(String ruleCode, int size) {
        return this.batchGet(ruleCode,size);
    }

    @Override
    public String functionForeseeTest(SysCodeRuleGenerate sysCodeRuleGenerate, RuleParam param) {
        if(StrUtil.equals(sysCodeRuleGenerate.getRuleType(), CodeRuleTypeEnum.BUSINESS.getType())){
            sysCodeRuleGenerate.setRuleCode(sysCodeRuleGenerate.getRuleCode()+"_TMP");
            ArrayList<RuleModel> rules = new ArrayList<>();
            rules.add(OrikaUtils.convert(sysCodeRuleGenerate, RuleModel.class));
            codeRuleParser.cacheTmpRule(rules);
        }
        return codeRuleParser.batchUniqParse(sysCodeRuleGenerate.getRuleCode(),1,15).get(0);
    }

    @Override
    public R saveWithRedis(SysCodeRuleGenerate sysCodeRuleGenerate) {
        //使用uuid标识唯一编码
       if(StrUtil.isBlank(sysCodeRuleGenerate.getRuleCode())){
           sysCodeRuleGenerate.setRuleCode(IdUtil.fastSimpleUUID());
       }
        if (StrUtil.equals(sysCodeRuleGenerate.getRuleType(), CodeRuleTypeEnum.BUSINESS.getType()) && StrUtil.isBlank(sysCodeRuleGenerate.getRuleParam())) {
            return R.failed("业务规则需要指定参数！");
        }
        if (StrUtil.equals(sysCodeRuleGenerate.getRuleType(), CodeRuleTypeEnum.SYSTEM.getType()) && StrUtil.isBlank(sysCodeRuleGenerate.getImplementClass())) {
            return R.failed("系统规则需要指定实现类！");
        }
        if (this.getOne(new QueryWrapper<SysCodeRuleGenerate>().eq("rule_code", sysCodeRuleGenerate.getRuleCode())) != null) {
            return R.failed(String.format("%s规则已存在，请重新输入", sysCodeRuleGenerate.getRuleCode()));
        }
        boolean save = this.save(sysCodeRuleGenerate);
        if (save) {
            codeRuleParser.cacheEvitRule(sysCodeRuleGenerate.getRuleCode());
            ArrayList<RuleModel> rules = new ArrayList<>();
            rules.add(OrikaUtils.convert(sysCodeRuleGenerate, RuleModel.class));
            codeRuleParser.cacheRule(rules);
        }
        return R.ok(save);
    }

    @Override
    public R updateWithRedisById(SysCodeRuleGenerate sysCodeRuleGenerate) {
        SysCodeRuleGenerate generate = this.getById(sysCodeRuleGenerate);
        Optional.ofNullable(generate).orElseThrow(()->new BizException("找不到对应规则数据！"));
        boolean flag = StrUtil.equals(sysCodeRuleGenerate.getRuleType(), CodeRuleTypeEnum.SYSTEM.getType()) &&
                sysCodeRuleGenerate.getImplementClass().startsWith("com.gitee.zeric.codec.generaters");
        if (flag) {
            return R.failed("系统内置规则无法修改！");
        }
        boolean update = this.updateById(sysCodeRuleGenerate);
        if (update) {
            ArrayList<RuleModel> rules = new ArrayList<>();
            rules.add(OrikaUtils.convert(sysCodeRuleGenerate, RuleModel.class));
            codeRuleParser.cacheRule(rules);
        }
        return R.ok(update);
    }

    @Override
    public R removeWithRedisById(Integer id) {
        SysCodeRuleGenerate sysCodeRuleGenerate = this.getById(id);
        if(StrUtil.equals(sysCodeRuleGenerate.getRuleType(),"2")){
            long count = this.count(new LambdaQueryWrapper<SysCodeRuleGenerate>().like(SysCodeRuleGenerate::getRulePlaceholder, "{" + sysCodeRuleGenerate.getRuleCode() + "}"));
            if(count!=0){return R.failed("有其规则使用该常量，无法删除！");}
        }

        Optional.ofNullable(sysCodeRuleGenerate).orElseThrow(()->new BizException("找不到对应规则数据！"));
        boolean flag = StrUtil.equals(sysCodeRuleGenerate.getRuleType(), CodeRuleTypeEnum.SYSTEM.getType()) &&
                sysCodeRuleGenerate.getImplementClass().startsWith("com.gitee.zeric.codec.generaters");
        if (flag) {
            return R.failed("系统内置规则无法删除！");
        }
        boolean save = this.removeById(id);
        if (save) {
            codeRuleParser.cacheEvitRule(sysCodeRuleGenerate.getRuleCode());
        }
        return R.ok(save);
    }


    @Override
    public void afterPropertiesSet() throws Exception {
        List<SysCodeRuleGenerate> sysCodeRuleGenerates = this.list();
        codeRuleParser.cacheRule(OrikaUtils.convertList(sysCodeRuleGenerates, RuleModel.class));
    }

}
